#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>

int main(int argc,char* argv[])
{
	if(argc != 3)
	{
		perror("argc");
		return 1;
	}

	int sockfd=socket(AF_INET,SOCK_STREAM,0);
	if(sockfd<0)
	{
		perror("socket");
		return 2;
	}

	struct sockaddr_in local;
	local.sin_family=AF_INET;
	local.sin_port=htons(atoi(argv[2]));
	local.sin_addr.s_addr=inet_addr(argv[1]);

	if(bind(sockfd,(struct sockaddr*)&local,sizeof(local))<0)
	{
		perror("bind");
		return 3;
	}

	if(listen(sockfd,2)==-1)
	{
		perror("listen");
		return 5;
	}

	while(1)
	{
		struct sockaddr_in client;
		socklen_t len=sizeof(client);
		int new_sockfd=accept(sockfd,(struct sockaddr*)&client,&len);
		if(new_sockfd<0)
		{
			perror("accept");
			return 6;
		}
		pid_t pid=fork();
		if(pid==0)
		{
			if(fork()==0)
			{
				char buf[128];
				while(1)
				{
					ssize_t rec=recv(new_sockfd,buf,sizeof(buf),0);
					if(rec < 0)
					{
						perror("recvfrom");
						return 4;
					}
					if(rec == 0)
					{
						break;
					}
					buf[rec]=0;
					printf("[%s,%d]: > %s\n",inet_ntoa(client.sin_addr),\
							ntohs(client.sin_port),buf);

					send(new_sockfd,buf,strlen(buf),0);
				}
				close(new_sockfd);
				exit(2);
			}
			else
			{
				exit(1);
			}
		}
		else
		{
			waitpid(pid,0,0);
		}
	}
	close(sockfd);

	return 0;
}
